home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Revista CD Expert 8
/
Revista CD Expert nº 08 CD1.iso
/
Utilitarios
/
Programacao
/
MS-DOS Interrupt List
/
inter60f
/
INT2RTF.ZIP
/
RTF.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-10-09
|
15KB
|
576 lines
{ RTF unit for the Interrupt List -> .RTF compiler. }
{ The software included, data formats and basic algorithms are }
{ copyright (C) 1996 by Slava Gostrenko. All rights reserved. }
{$X+}
unit
RTF;
interface
uses
Objects;
const
HexChars = ['0'..'9', 'A'..'F', 'a'..'f'];
TPFileStamp = '{\rtf1\pc \deff1{\fonttbl{\f0\froman Times New Roman;}'#$D#$A
+ '{\f1\fmodern Courier New;}}'#$D#$A
+ '{\colortbl \red255\green0\blue0;\red0\green0\blue0;'#$D#$A
+ '\red0\green0\blue255;\red255\green255\blue255;}'#$D#$A
+ '\plain\fs18\pard\keep'#$D#$A;
FileStamp : array [0 .. Length (TPFileStamp) - 1] of Char = TPFileStamp;
type
PIdxTbl = ^TIdxTbl;
TIdxTbl = object (TSortedCollection)
function KeyOf (Item: Pointer): Pointer; virtual;
function Compare (Key1, Key2: Pointer): Integer; virtual;
procedure SetCtxs;
end;
PTopic = ^TTopic;
TTopic = object (TStringCollection)
Header,
SubHeader: PString;
Keywords: TStringCollection;
InSwap: Boolean;
SwapPos: Longint;
constructor Init(ALimit, ADelta: Integer);
destructor Done; virtual;
procedure SetHeader (const S: string);
procedure SetSubHeader (const S: string);
procedure Store2Swap (var S: TStream);
procedure RestoreFromSwap (var S: TStream);
procedure AddString (S: string);
procedure Write (var S: TStream; var IdxTbl: TIdxTbl;
Ctx: Word; const Title: string);
procedure AddKeyword (S: string; StepBack: Integer);
procedure AddKeywordAtStart (S: string);
function ResolveKeyword (const I: Integer; var IdxTbl: TIdxTbl): Word;
end;
PIndexEntry = ^TIndexEntry;
TIndexEntry = object (TObject)
PS: PString;
Ctx: Word;
Topic: PTopic;
constructor Init (const S: string; ACtx: Word; var ATopic: PTopic);
destructor Done; virtual;
end;
PHelpFile = ^THelpFile;
THelpFile = object (TBufStream)
IdxTbl: TIdxTbl;
constructor Init(FileName: FNameStr; Mode, Size: Word);
destructor Done; virtual;
end;
var
SwapFile: PBufStream;
BoldNames: TStringCollection;
implementation
uses
Upcaser;
const EmptyString : string[1] = '';
function PStr(P: PString): PString; {returns pointer to empty string if p = nil}
inline (
$58/ {Pop AX}
$5A/ {Pop DX}
$0B/ $D2/ {Or DX, DX}
$75/ $05/ {JNE Exit}
$8C/ $DA/ {MOV DX, DS}
$B8/ >EmptyString {MOV AX, offset EmptyString}
);
{ TTopic = object (TStringCollection) }
constructor TTopic. Init(ALimit, ADelta: Integer);
begin
inherited Init (ALimit, ADelta);
Keywords. Init (ALimit, ADelta);
InSwap := False;
SwapPos := -1;
Header := nil;
SubHeader := nil;
end;
destructor TTopic. Done;
begin
DisposeStr (Header);
DisposeStr (SubHeader);
inherited Done;
end;
procedure TTopic. SetHeader (const S: string);
begin
Header := NewStr (S);
end;
procedure TTopic. SetSubHeader (const S: string);
begin
SubHeader := NewStr (S);
end;
procedure TTopic. Store2Swap (var S: TStream);
var I: Integer;
begin
if not InSwap then begin
if SwapPos = -1 then begin
SwapPos := S. GetSize;
S. Seek (SwapPos);
S. Write (Count, 2);
if Count > 0 then
for I := 0 to Count - 1 do begin
S. WriteStr (Items^[I]);
DisposeStr (Items^[I]);
Items^[I] := nil;
end;
S. WriteStr (SubHeader);
DisposeStr (SubHeader);
SubHeader := nil;
end else begin
if Count > 0 then
for I := 0 to Count - 1 do begin
DisposeStr (Items^[I]);
Items^[I] := nil;
end;
DisposeStr (SubHeader);
SubHeader := nil;
end;
InSwap := True;
end;
end;
procedure TTopic. RestoreFromSwap (var S: TStream);
var I, C: Integer;
begin
if InSwap then
if SwapPos = -1 then begin
WriteLn ('Swapping error 2');
Halt (1);
end else begin
S. Seek (SwapPos);
S. Read (C, 2);
if C > 0 then
for I := 0 to C - 1 do
Items^[I] := S. ReadStr;
SubHeader := S. ReadStr;
InSwap := False;
end;
end;
procedure TTopic. AddString (S: string);
begin
AtInsert (Count, NewStr (S));
end;
procedure TTopic. Write (var S: TStream; var IdxTbl: TIdxTbl;
Ctx: Word; const Title: string);
const StartTopic = '\pard\keepn\li1060\fi-1060'#$D#$A;
StartTopicStr: string [Length (StartTopic)] = StartTopic;
var KeywordN: Integer;
DropOnePar: Boolean;
procedure DoWrite (Str: string; NoPar: Boolean);
procedure MakeBold (var S: string); far;
var OldI, I: Integer;
begin
OldI := 0;
I := Pos (S, Str);
while I > 0 do begin
Inc (I, OldI);
System. Insert (#4, Str, I + Length (S));
System. Insert (#3, Str, I);
OldI := I + Length (S) + 1;
I := Pos (S, Copy (Str, I + Length (S) + 2, Length (Str)));
end;
end;
const EOL: string [2] = #$D#$A;
Par: string [4] = '\par';
StartKey: string [7] = '{\uldb ';
EndKey: string [5] = '}{\v ';
StartBold: string [4] = '{\b ';
var I: Integer;
C: Char;
LinkStr: string;
StartFrom: Integer;
begin
BoldNames. ForEach (@MakeBold);
StartFrom := 1;
if NoPar then begin
if (Length (Str) > 0) and (Str [1] = ' ') then
StartFrom := 2;
end else begin
S. Write (Par [1], Length (Par));
if (Length (Str) > 0) and (Str [1] <> ' ') then begin
C := ' '; S. Write (C, 1);
end;
end;
for I := StartFrom to Length (Str) do
case Str [I] of
#2: begin
if Odd (KeywordN) then begin
S. Write (EndKey [1], Length (EndKey));
System. Str (ResolveKeyword (KeywordN div 2, IdxTbl), LinkStr);
S. Write (LinkStr [1], Length (LinkStr));
C := '}'; S. Write (C, 1);
end else
S. Write (StartKey [1], Length (StartKey));
Inc (KeywordN);
end;
#3: S. Write (StartBold [1], Length (StartBold));
#4: begin C := '}'; S. Write (C, 1); end;
'ü': begin C := 'u'; S. Write (C, 1); end;
'µ': begin C := 'u'; S. Write (C, 1); end;
'²': begin C := '2'; S. Write (C, 1); end;
'á': begin C := 'a'; S. Write (C, 1); end;
'─': begin C := '-'; S. Write (C, 1); end;
'│': begin C := '|'; S. Write (C, 1); end;
'┬': begin C := '+'; S. Write (C, 1); end;
'┴': begin C := '+'; S. Write (C, 1); end;
'├': begin C := '+'; S. Write (C, 1); end;
'┤': begin C := '+'; S. Write (C, 1); end;
'┼': begin C := '+'; S. Write (C, 1); end;
'┌': begin C := '+'; S. Write (C, 1); end;
'┐': begin C := '+'; S. Write (C, 1); end;
'└': begin C := '+'; S. Write (C, 1); end;
'┘': begin C := '+'; S. Write (C, 1); end;
'╒': begin C := '+'; S. Write (C, 1); end;
'╤': begin C := '+'; S. Write (C, 1); end;
'╕': begin C := '+'; S. Write (C, 1); end;
'╞': begin C := '+'; S. Write (C, 1); end;
'╪': begin C := '+'; S. Write (C, 1); end;
'╡': begin C := '+'; S. Write (C, 1); end;
'╘': begin C := '+'; S. Write (C, 1); end;
'╧': begin C := '+'; S. Write (C, 1); end;
'╛': begin C := '+'; S. Write (C, 1); end;
'═': begin C := '='; S. Write (C, 1); end;
'Σ': begin C := 'E'; S. Write (C, 1); end;
'é': begin C := 'e'; S. Write (C, 1); end;
'ä': begin C := 'a'; S. Write (C, 1); end;
'ó': begin C := 'o'; S. Write (C, 1); end;
'ö': begin C := 'o'; S. Write (C, 1); end;
'\', '{', '}':
begin
C := '\'; S. Write (C, 1);
S. Write ((@(Str [I]))^, 1);
end;
else
S. Write ((@(Str [I]))^, 1);
end;
S. Write (EOL [1], 2);
end;
procedure WriteOneString (PS: PString); far;
begin
if PS <> nil then
DoWrite (PS^, DropOnePar)
else
DoWrite ('', DropOnePar);
DropOnePar := False;
end;
var CtxStr, Str: string;
begin
RestoreFromSwap (SwapFile^);
S. Write (StartTopicStr [1], Length (StartTopicStr));
System. Str (Ctx, CtxStr);
Str := '#{\footnote{#} ' + CtxStr + '}'#$D#$A;
S. Write (Str [1], Length (Str));
Str := '${\footnote{$} ' + Title + '}'#$D#$A;
S. Write (Str [1], Length (Str));
Str := '+{\footnote{+} l:0}'#$D#$A;
S. Write (Str [1], Length (Str));
Str := 'K{\footnote{K} ' + Title + '}'#$D#$A;
S. Write (Str [1], Length (Str));
KeywordN := 0;
Str := '{\f0\fs28\keep ';
S. Write (Str [1], Length (Str));
if Header <> nil then
DoWrite (Header^, True)
else
DoWrite (Title, True);
if SubHeader <> nil then begin
Str := '{\fs24 ';
S. Write (Str [1], Length (Str));
DoWrite (SubHeader^, False);
Str := '}';
S. Write (Str [1], Length (Str));
end;
Str := '}\par\pard\keep'#$D#$A;
S. Write (Str [1], Length (Str));
DropOnePar := True;
ForEach (@WriteOneString);
Store2Swap (SwapFile^);
end;
procedure TTopic. AddKeyword (S: string; StepBack: Integer);
begin
Keywords. AtInsert (Keywords. Count - StepBack, NewStr (S));
end;
procedure TTopic. AddKeywordAtStart (S: string);
begin
Keywords. AtInsert (0, NewStr (S));
end;
function TTopic. ResolveKeyword (const I: Integer; var IdxTbl: TIdxTbl): Word;
var
TmpW: Word;
J, K, MinL, SaveMinLIdx, MatchLen, DecCnt: Integer;
TmpS, MatchS, Helper: string;
MatchFound: Boolean;
begin
if (Keywords. Count > I) and (I >= 0) then begin
TmpS := StUpcase2 (PString (Keywords. At (I))^);
J := Pos ('"', TmpS);
if J > 0 then begin
if TmpS [Length (TmpS)] <> '"' then begin
Helper := '';
WriteLn ('error in keyword format - ', TmpS)
end else begin
Helper := Copy (TmpS, J + 1, Length (TmpS) - J - 1);
TmpS [0] := Chr (J - 1);
end;
end else
Helper := '';
DecCnt := 0;
MatchFound := False;
MinL := High (MinL);
repeat
IdxTbl. Search (@TmpS, J);
for K := J to IdxTbl. Count - 1 do begin
MatchS := StUpcase2 (PIndexEntry (IdxTbl. At (K))^.PS^);
if Copy (MatchS, 1, Length (TmpS))
<> TmpS then
Break
else begin
if ((Helper = '')
or (Pos (Helper, StUpcase2 (PIndexEntry (
IdxTbl. At (K))^. Topic^. Header^)) > 0))
and (Length (MatchS) - Length (TmpS) < MinL)
then begin
MinL := Length (MatchS) - Length (TmpS);
MatchLen := Length (TmpS);
SaveMinLIdx := K;
end;
end;
end;
if (DecCnt < 2) and (MinL < High (MinL)) then begin
MatchFound := True;
J := SaveMinLIdx;
end;
Dec (TmpS [0]);
Inc (DecCnt);
until MatchFound or (Length (TmpS) < 2);
if (Helper <> '') and (MinL < High (MinL)) then
MinL := 0;
if not MatchFound then begin
MatchFound := MinL < High (MinL);
J := SaveMinLIdx;
end;
if ( ((Helper = '') or (MinL = High (MinL)))
and (((MatchLen < 4) and (MinL > 0)) or (MinL > 1))
)
and (TmpS [1] in HexChars) and (TmpS [2] in HexChars) then begin
TmpS := 'INT ' + TmpS [1] + TmpS [2];
if not IdxTbl. Search (@TmpS, J) then begin
WriteLn ('error searching for - ', TmpS);
end else begin
MinL := 0;
MatchFound := True;
end;
end;
if ( ((Helper = '') or (MinL = High (MinL)))
and (((MatchLen < 5) and (MinL > 0)) or (MinL > 1))
)
and (TmpS [1] = 'P')
and (TmpS [2] in HexChars + ['x', 'X']) and (TmpS [3] in HexChars + ['x', 'X'])
and (TmpS [4] in HexChars + ['x', 'X']) and (TmpS [5] in HexChars + ['x', 'X']) then begin
TmpS := 'PORTS';
if not IdxTbl. Search (@TmpS, J) then begin
WriteLn ('error searching for - ', TmpS);
end else begin
MinL := 0;
MatchFound := True;
end;
end;
TmpW := PIndexEntry (IdxTbl. At (J))^.Ctx;
if not MatchFound then begin
WriteLn (Header^);
WriteLn ('error searching for - ', PString (Keywords. At (I))^);
WriteLn ('found match - ', PIndexEntry (IdxTbl. At (J))^.PS^);
TmpW := 1;
end else
if MinL > 1 then begin
WriteLn (Header^);
WriteLn ('approximate match to - ', PString (Keywords. At (I))^);
WriteLn ('is - ', PIndexEntry (IdxTbl. At (J))^.PS^);
TmpW := 1;
end;
ResolveKeyword := TmpW;
end else begin
WriteLn ('Internal error - invalid keyword number');
Halt (1);
end;
end;
{ TIndexEntry = object (TObject) }
constructor TIndexEntry. Init (const S: string; ACtx: Word; var ATopic: PTopic);
begin
inherited Init;
PS := NewStr (S);
Ctx := ACtx;
Topic := ATopic;
ATopic := nil;
Topic^.Store2Swap (SwapFile^);
if Topic^.Header = nil then
Topic^.SetHeader (S);
end;
destructor TIndexEntry. Done;
begin
DisposeStr (PS);
inherited Done;
end;
{ TIdxTbl = object (TSortedCollection) }
function TIdxTbl. KeyOf (Item: Pointer): Pointer;
begin
KeyOf := PIndexEntry (Item)^. PS;
end;
function TIdxTbl. Compare (Key1, Key2: Pointer): Integer;
begin
if (Key1 = nil) or (StUpcase2 (PString (Key1)^) < StUpcase2 (PString (Key2)^)) then
Compare := -1
else
if (Key2 <> nil) and (StUpcase2 (PString (Key1)^) = StUpcase2 (PString (Key2)^)) then
Compare := 0
else
Compare := 1;
end;
procedure TIdxTbl. SetCtxs;
var I: Integer;
begin
for I := 0 to Count - 1 do
PIndexEntry (At (I))^. Ctx := I + 1;
end;
{ THelpFile = object (TBufStream) }
constructor THelpFile.Init(FileName: FNameStr; Mode, Size: Word);
begin
inherited Init (FileName, Mode, Size);
if Mode = stCreate then
Write (FileStamp, SizeOf (FileStamp));
IdxTbl. Init (MaxCollectionSize, 0);
IdxTbl. Duplicates := True;
end;
destructor THelpFile.Done;
const NewPage: string [5] = '\page';
EndOfFile: Char = '}';
var I: Integer;
begin
IdxTbl. SetCtxs;
System. Write (' '#13);
for I := 0 to IdxTbl.Count - 1 do begin
if I > 0 then
Write (NewPage [1], 5);
PIndexEntry (IdxTbl. At (I))^.Topic^.Write (
Self,
IdxTbl,
PIndexEntry (IdxTbl. At (I))^. Ctx,
PStr (PIndexEntry (IdxTbl. At (I))^. PS)^);
System. Write (I, #13);
end;
Write (EndOfFile, SizeOf (EndOfFile));
IdxTbl. Done;
inherited Done;
end;
end.